//数据劫持文件
import { newArrayProto } from "./array";
import Dep from "./dep";
class Observer {
  constructor(data) {
    // 给每个对象增加收集功能
    this.dep = new Dep();
    Object.defineProperty(data, "__ob__", { //使用defineProperty重新定义对象属性
      value: this,
      enumerable: false
    })
    // data.__ob__ = this;
    if (Array.isArray(data)) {
      //重写数组方法
      data.__proto__ = newArrayProto;
      this.observeArray(data); //监控数组里面的对象
    } else {
      this.walk(data);
    }
  }
  walk(data) { //循环对象，对属性进行劫持
    //循环 ”重新定义“属性
    Object.keys(data).forEach(key => defineReactive(data, key, data[key]))
  }
  //监控数组对象方法
  observeArray(data) {
    data.forEach(item => observe(item));
  }
}
function dependArray(value) {
  for(let i = 0; i < value.length; i++) {
    let current = value[i]
    current.__ob__ && current.__ob__.dep.depend();
    if(Array.isArray(current)) {
      dependArray(current);
    }
  }
}
//对象数据劫持核心代码
export function defineReactive(target, key, value) { //闭包 属性劫持
  //对象里面还有对象 再次 数据劫持 使用递归
  let childob = observe(value);
  let dep = new Dep(); //给每个属性增加dep
  Object.defineProperty(target, key, {
    get() { //取值
      if(Dep.target) {
        dep.depend(); //记住当前的watch,加入dep收集中
        if(childob) {
          childob.dep.depend();
          if(Array.isArray(value)) { //为了解决数组里套数组
            dependArray(value);
          }
        }
      }
      return value;
    },
    set(newValue) { // 设置值
      if (newValue == value) return;
      observe(newValue) //用户修改值传的是一个对象
      value = newValue;
      dep.notify(); //通知更新
    }
  })
}
export function observe(data) {
  if (typeof data !== 'object' || data == null) {
    return; //只对对象进行劫持
  }
  if (data.__ob__ instanceof Observer) { //说明被代理过来
    return data.__ob__;
  }
  return new Observer(data)
}